﻿
Imports std
Imports centrosphere
Imports centrosphere.job
Imports command = centrosphere.job.storage.command

Partial Public Class storageJobRedundanceDistributor
    Inherits storageJobDistributor

    Private _redundanceCount As UInt32 = 0
    Private Property redundanceCount() As UInt32
        Get
            assert(_redundanceCount > 0)
            Return _redundanceCount
        End Get
        Set(ByVal value As UInt32)
            assert(_redundanceCount = 0)
            assert(value > 0)
            If value > targetQueues().size() Then
                raiseError(errorHandle.errorType.warning,
                           "redundanceCount ", value, " is larger than targetQueues.size ", targetQueues().size(),
                           ", use targetQueues.size instead.")
                value = targetQueues().size()
            End If
            _redundanceCount = value
        End Set
    End Property

    Private _verifyRate As SByte = npos
    Private Property verifyRate() As SByte
        Get
            assert(_verifyRate >= 0)
            Return _verifyRate
        End Get
        Set(ByVal value As SByte)
            assert(_verifyRate = npos)
            assert(value >= 0)
            _verifyRate = value
        End Set
    End Property

    Private Function passVerifyRate() As Boolean
        Return verifyRate() = 100 OrElse rnd(0, 100, True) < verifyRate()
    End Function

    Private Shared ReadOnly distribute_verifiable_commands() As command = {command.read,
                                                                           command.seek,
                                                                           command.sizeof}

    Private Shared Function distribute_verifiable_command(ByVal i As command) As Boolean
        assert(storage.valid(i))
        Return distribute_verifiable_commands.has(i)
    End Function

    Private Shared Function distribute_verifiable_job(ByVal i As storageJob) As Boolean
        assert(Not i Is Nothing)
        Return distribute_verifiable_command(i.command)
    End Function

    Private Shared Function distribute_verifiable_job(ByVal i As indexedJob) As Boolean
        Return distribute_verifiable_job(storageJob(i))
    End Function

    Private Shared ReadOnly sync_modify_aggregate_commands() As command = {command.read,
                                                                           command.modify}

    Private Shared Function sync_modify_aggregate_command(ByVal i As command) As Boolean
        Return sync_modify_aggregate_commands.has(i)
    End Function

    Private Shared ReadOnly sync_read_modify_aggregate_commands() As command = {command.seek,
                                                                                command.sizeof,
                                                                                command.write,
                                                                                command.uniqueWrite}

    Private Shared Function sync_read_modify_aggregate_command(ByVal i As command) As Boolean
        Return sync_read_modify_aggregate_commands.has(i)
    End Function

    Private Shared ReadOnly one_success_aggregate_commands() As command = {command.delete,
                                                                           command.full}

    Private Shared Function one_success_aggregate_command(ByVal i As command) As Boolean
        Return one_success_aggregate_commands.has(i)
    End Function

    Private Shared ReadOnly all_success_aggregate_commands() As command = {command.open,
                                                                           command.close,
                                                                           command.health,
                                                                           command.retire,
                                                                           command.empty,
                                                                           command.sync,
                                                                           command.version,
                                                                           command.lockwrite,
                                                                           command.unlockwrite,
                                                                           command.lockread,
                                                                           command.unlockread,
                                                                           command.lock,
                                                                           command.unlock}

    Private Shared Function all_success_aggregate_command(ByVal i As command) As Boolean
        Return all_success_aggregate_commands.has(i)
    End Function

    Private Shared ReadOnly max_div_aggregate_commands() As command = {command.valuesize,
                                                                       command.keycount}

    Private Shared Function max_div_aggregate_command(ByVal i As command) As Boolean
        Return max_div_aggregate_commands.has(i)
    End Function

    Private Shared ReadOnly min_aggregate_commands() As command = {command.capacity}

    Private Shared Function min_aggregate_command(ByVal i As command) As Boolean
        Return min_aggregate_commands.has(i)
    End Function

    Private Shared ReadOnly sum_aggregate_commands() As command = {command.status}

    Private Shared Function sum_aggregate_command(ByVal i As command) As Boolean
        Return sum_aggregate_commands.has(i)
    End Function

    Private Shared Function valid_targetJobs(ByVal targetJobs() As indexedJob) As Boolean
        If targetJobs Is Nothing OrElse targetJobs.Length() = 0 Then
            Return False
        Else
            Dim cmd As command = Nothing
            cmd = storageJob(targetJobs(0)).command
            If storage.valid(cmd) Then
                For i As Int64 = 1 To targetJobs.Length() - 1
                    If storageJob(targetJobs(i)).command <> cmd Then
                        Return False
                    End If
                Next

                Return True
            Else
                Return False
            End If
        End If
    End Function

    Private Shared Shadows Function initial(ByVal name As String,
                                            ByVal config As configParser,
                                            ByVal i As storageJobRedundanceDistributor) As Boolean
        If distributor.initial(name, config, i) Then
            Dim rc As UInt32 = 0
            If config.getparameter(name, "redundanceCount", rc) Then
                i.redundanceCount() = rc
            Else
                i.redundanceCount() = 3
            End If
            Dim vr As SByte = 0
            If config.getparameter(name, "verifyRate", vr) Then
                i.verifyRate() = vr
            Else
                i.verifyRate() = 50
            End If
            Return True
        Else
            Return False
        End If
    End Function

    Public Shared Shadows Function initial(ByRef name As String,
                                           ByRef config As configParser,
                                           ByRef i As Object) As Boolean
        Return initial(name, config, convertor.cast(Of storageJobRedundanceDistributor)(i))
    End Function

    Public Sub New()
        all_aggregators = initial_all_aggregators()
        redundance_count = Function() redundanceCount()
    End Sub
End Class
